package com.vegetable.modules.service.finance.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vegetable.common.constant.CommonConstant;
import com.vegetable.common.utils.Constant;
import com.vegetable.common.utils.PageUtils;
import com.vegetable.common.utils.Query;
import com.vegetable.common.utils.R;
import com.vegetable.modules.entity.baseData.AccountDetails;
import com.vegetable.modules.entity.baseData.AddressBook;
import com.vegetable.modules.entity.finance.PaymentAccountRelease;
import com.vegetable.modules.entity.finance.PaymentPurchase;
import com.vegetable.modules.entity.finance.PaymentPurchaseDetail;
import com.vegetable.modules.entity.finance.po.AgentDeliveryStatisticsPO;
import com.vegetable.modules.entity.finance.po.PaymentPurchaseAddPO;
import com.vegetable.modules.entity.finance.po.PurchaseDeliveryStatisticsPO;
import com.vegetable.modules.entity.finance.vo.PaymentAgentStatisticsVO;
import com.vegetable.modules.entity.finance.vo.PaymentPurchaseStatisticsVO;
import com.vegetable.modules.entity.inbound.AgentDelivery;
import com.vegetable.modules.entity.inbound.PurchaseDelivery;
import com.vegetable.modules.mapper.finance.PaymentPurchaseMapper;
import com.vegetable.modules.service.baseData.IAccountDetailsService;
import com.vegetable.modules.service.baseData.IAddressBookService;
import com.vegetable.modules.service.baseData.IFundAccountService;
import com.vegetable.modules.service.finance.IPaymentAccountReleaseService;
import com.vegetable.modules.service.finance.IPaymentPurchaseDetailService;
import com.vegetable.modules.service.finance.IPaymentPurchaseService;
import com.vegetable.modules.service.inbound.IAgentDeliveryDetailService;
import com.vegetable.modules.service.inbound.IAgentDeliveryService;
import com.vegetable.modules.service.inbound.IPurchaseDeliveryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 采购/代办付款 服务实现类
 * </p>
 *
 * @author wangruijie
 * @since 2024-04-15
 */
@Slf4j
@Service
public class PaymentPurchaseServiceImpl extends ServiceImpl<PaymentPurchaseMapper, PaymentPurchase> implements IPaymentPurchaseService {
    @Autowired
    private IPaymentPurchaseDetailService detailService;
    @Autowired
    // 通讯录
    private IAddressBookService addressBookService;
    // 往来明细
    @Autowired
    private IAccountDetailsService accountDetailsService;
    // 待办交货
    @Autowired
    private IAgentDeliveryService agentDeliveryService;
    @Autowired
    private IAgentDeliveryDetailService iAgentDeliveryDetailService;
    // 采购收货
    @Autowired
    private IPurchaseDeliveryService purchaseDeliveryService;
    @Autowired
    private IFundAccountService accountService;
    @Autowired
    private IPaymentAccountReleaseService iPaymentAccountReleaseService;

    /**
     * 采购/代办付款列表查询
     * @param params
     * @return
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String docNo = (String)params.get("docNo");
        // 状态0结账未付，1实际已付
        Object state = params.get("state");
        // 审批状态 0未提交审批，1审批中，2审批通过，3审批拒绝
        Object approvalState = params.get("approvalState");
        Object orderType = params.get("orderType");
        String startTime = (String)params.get("startTime");
        String endTime = (String)params.get("endTime");
        IPage<PaymentPurchase> page = this.page(
                new Query<PaymentPurchase>().getPage(params),
                new QueryWrapper<PaymentPurchase>()
                        .between(StringUtils.isNotBlank(startTime), "order_time", startTime, endTime)
                        .eq(ObjectUtils.isNotEmpty(state),"state", state)
                        .eq(ObjectUtils.isNotEmpty(approvalState),"approval_state", approvalState)
                        .eq(ObjectUtils.isNotEmpty(orderType),"order_type", orderType)
                        .eq(ObjectUtils.isNotEmpty(params.get("customerId")),"customer_id", params.get("customerId"))
                        .like(StringUtils.isNotBlank(docNo),"doc_no", docNo)
                        .orderByAsc("state").orderByDesc("create_time")
        );
        List<PaymentPurchase> records = page.getRecords();
        if(CollectionUtil.isNotEmpty(records)){
            List<Long> ids = records.stream().map(el -> el.getId()).collect(Collectors.toList());
            List<PaymentAccountRelease> releases = iPaymentAccountReleaseService.selectByMainIds(ids);
            // 批量查询所有记录的付款明细
            List<PaymentPurchaseDetail> allDetails = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(ids)) {
                QueryWrapper<PaymentPurchaseDetail> detailWrapper = new QueryWrapper<>();
                detailWrapper.in("main_id", ids);
                allDetails = detailService.getBaseMapper().selectList(detailWrapper);
            }
            
            // 收集所有orderId用于批量查询AgentDelivery记录
            Set<Long> orderIds = new HashSet<>();
            for(PaymentPurchase record : records){
                List<PaymentAccountRelease> currentList = releases.stream().filter(el -> el.getMainId().equals(record.getId())).collect(Collectors.toList());
                record.setAccountReleases(currentList);
                
                // 设置付款明细
                List<PaymentPurchaseDetail> payDetails = allDetails.stream()
                    .filter(detail -> detail.getMainId().equals(record.getId()))
                    .collect(Collectors.toList());
                record.setPayDetails(payDetails);
                
                // 收集所有orderId
                if (CollectionUtil.isNotEmpty(payDetails)) {
                    for (PaymentPurchaseDetail detail : payDetails) {
                        if (detail.getOrderId() != null) {
                            orderIds.add(detail.getOrderId());
                        }
                    }
                }
            }
            
            // 批量查询所有AgentDelivery记录
            List<AgentDelivery> agentDeliveries = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(orderIds)) {
                agentDeliveries = agentDeliveryService.listByIds(new ArrayList<>(orderIds));
            }
            
            // 创建orderId到AgentDelivery的映射，提高查找效率
            Map<Long, AgentDelivery> agentDeliveryMap = agentDeliveries.stream()
                .collect(Collectors.toMap(AgentDelivery::getId, ad -> ad, (existing, replacement) -> existing));
            
            // 处理每条记录的商品名称
            for(PaymentPurchase record : records){
                List<PaymentPurchaseDetail> payDetails = record.getPayDetails();
                
                // 根据payDetails中的orderId查询AgentDelivery记录，提取commodityNames字段并去重合并
                String finishCommodityNames = buildFinishCommodityNames(payDetails, agentDeliveryMap);
                if (StringUtils.isNotBlank(finishCommodityNames)) {
                    record.setFinishCommodityNames(finishCommodityNames);
                }
            }
        }
        return new PageUtils(page);
    }

    /**
     * 根据id查询详情采购付款
     * @param id null
     * @return R
     * @author wrj
     * @since 2024/4/28 下午4:52
     */
    @Override
    public R detailPurchase(Long id) {
        PaymentPurchase purchase = baseMapper.selectById(id);
        QueryWrapper<PaymentPurchaseDetail> wrapper = new QueryWrapper();
        wrapper.eq("main_id", purchase.getId());
        List<PaymentPurchaseDetail> details = detailService.getBaseMapper().selectList(wrapper);
        List<PaymentAccountRelease> accountReleases = iPaymentAccountReleaseService.selectByMainId(id);
        purchase.setPayDetails(details);
        purchase.setAccountReleases(accountReleases);
        
        // 根据payDetails中的orderId查询AgentDelivery记录，提取commodityNames字段并去重合并
        if (CollectionUtil.isNotEmpty(details)) {
            // 收集所有orderId用于批量查询
            Set<Long> orderIds = new HashSet<>();
            for (PaymentPurchaseDetail detail : details) {
                if (detail.getOrderId() != null) {
                    orderIds.add(detail.getOrderId());
                }
            }
            
            // 批量查询所有AgentDelivery记录
            List<AgentDelivery> agentDeliveries = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(orderIds)) {
                agentDeliveries = agentDeliveryService.listByIds(new ArrayList<>(orderIds));
            }
            
            // 创建orderId到AgentDelivery的映射，提高查找效率
            Map<Long, AgentDelivery> agentDeliveryMap = agentDeliveries.stream()
                .collect(Collectors.toMap(AgentDelivery::getId, ad -> ad, (existing, replacement) -> existing));
            
            // 根据payDetails中的orderId查询AgentDelivery记录，提取commodityNames字段并去重合并
            String finishCommodityNames = buildFinishCommodityNames(details, agentDeliveryMap);
            if (StringUtils.isNotBlank(finishCommodityNames)) {
                purchase.setFinishCommodityNames(finishCommodityNames);
            }
        }
        
        return R.data(purchase);
    }

    /**
     * 新增采购付款
     * @param payment null
     * @return R
     * @author wrj
     * @since 2024/3/7 下午4:35
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R savePayment(PaymentPurchaseAddPO payment) throws Exception {
        if (CollectionUtils.isEmpty(payment.getPayDetails())){
            return R.fail("明细不能为空");
        }
        // 确认提交
        BigDecimal sumMoney = BigDecimal.ZERO;
        BigDecimal money = BigDecimal.ZERO;
        BigDecimal discount = BigDecimal.ZERO;
        for (PaymentPurchaseDetail detailPO:payment.getPayDetails()) {
            money = money.add(detailPO.getMoney());
            discount = discount.add(detailPO.getDiscount()==null?BigDecimal.ZERO:detailPO.getDiscount());
            sumMoney = sumMoney.add(money).add(discount);
            // 修改采购收货 未对账金额
            PurchaseDelivery delivery = purchaseDeliveryService.getById(detailPO.getOrderId());
            if(delivery.getIsPayFinish() == 1){
                throw new Exception(delivery.getDocNo() + "已经收完款了，不能重复收款");
            }
            BigDecimal verifyMonet = delivery.getVerifyMonet();
            verifyMonet = verifyMonet.subtract(detailPO.getMoney());
            if (payment.getState() == 1){
                // 新增农户的往来明细
                saveAccountDetails(payment.getCustomerId(), detailPO, 0, 3);
                if (detailPO.getOrderId() == null){
                    throw new Exception("采购收货单不存在");
                }
                delivery.setIsPayFinish(1);
            }else {
                delivery.setIsPayFinish(2);
            }
            detailPO.setOrderTime(delivery.getOrderTime());
            delivery.setVerifyMonet(verifyMonet);
            payment.setCustomerId(delivery.getCustomerId());
            payment.setCustomerName(delivery.getCustomerName());
            purchaseDeliveryService.updateById(delivery);
        }
        payment.setMoney(NumberUtil.sub(money, payment.getGlobalDiscount()));
        payment.setDiscount(NumberUtil.add(discount, payment.getGlobalDiscount()));
        if (payment.getId() == null){
            payment.setDocNo(CommonConstant.CGFK+ baseMapper.getNextCode());
            payment.setOrderTime(new Date());
            PaymentPurchase tar = new PaymentPurchase();
            BeanUtils.copyProperties(payment, tar);
            save(tar);
            payment.setId(tar.getId());
        }else {
            QueryWrapper<PaymentPurchaseDetail> wrapper = new QueryWrapper();
            wrapper.eq("main_id", payment.getId());
            detailService.getBaseMapper().delete(wrapper);
            PaymentPurchase tar = new PaymentPurchase();
            BeanUtils.copyProperties(payment, tar);
            this.updateById(tar);

        }
        // 保存明细
        saveDetail(payment.getId(), payment.getPayDetails());

        // 状态0结账未付，1实际已付
        if (payment.getState() == 1){
            log.info("更新客商的应收金额：{},{}", payment.getCustomerId(), sumMoney);
            updateArrears(payment.getCustomerId(), sumMoney);
            // 更新总支出
//            FundAccount account_out = accountService.getById(payment.getAccountId());
//            if (account_out != null){
//                BigDecimal totalExpenditure = account_out.getTotalExpenditure();
//                totalExpenditure = totalExpenditure.add(money);
//                account_out.setTotalExpenditure(totalExpenditure);
//                accountService.updateById(account_out);
//            }
            accountService.addReceipts(payment.getAccountId(), payment.getMoney(), Constant.MoneyTYPE.PURCHASE_OUT, payment.getDocNo(), payment.getId(), payment.getCustomerName());

        }

        return R.status(true);
    }

    /**
     * 保存明细
     * @param id
     * @param payDetails
     */
    private void saveDetail(Long id, List<PaymentPurchaseDetail> payDetails){
        for (PaymentPurchaseDetail detail:payDetails) {
            detail.setMainId(id);
        }
        detailService.saveBatch(payDetails);
    }
    
    /**
     * 根据付款明细列表构建完成的商品名称字符串
     * @param payDetails 付款明细列表
     * @param agentDeliveryMap AgentDelivery映射
     * @return 去重后用"|"连接的商品名称字符串
     */
    private String buildFinishCommodityNames(List<PaymentPurchaseDetail> payDetails, Map<Long, AgentDelivery> agentDeliveryMap) {
        if (CollectionUtil.isEmpty(payDetails) || CollectionUtil.isEmpty(agentDeliveryMap)) {
            return null;
        }
        
        Set<String> commodityNameSet = new HashSet<>();
        for (PaymentPurchaseDetail detail : payDetails) {
            AgentDelivery agentDelivery = agentDeliveryMap.get(detail.getOrderId());
            if (agentDelivery != null && StringUtils.isNotBlank(agentDelivery.getCommodityNames())) {
                // 将"|"分割的字符串拆分为集合，然后添加到总的集合中以实现去重
                String[] names = agentDelivery.getCommodityNames().split("\\|");
                Collections.addAll(commodityNameSet, names);
                detail.setCommodityNames(agentDelivery.getCommodityNames());
            }
        }
        // 将去重后的商品名称用"|"连接成字符串
        if (!commodityNameSet.isEmpty()) {
            return commodityNameSet.stream().collect(Collectors.joining("|"));
        }
        return null;
    }

    /**
     * 新增代办付款
     * @param payment null
     * @return R
     * @author wrj
     * @since 2024/3/7 下午4:35
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R savePaymentAgent(PaymentPurchase payment) throws Exception {
        List<PaymentPurchaseDetail> payDetails = payment.getPayDetails();
        if (CollectionUtils.isEmpty(payDetails)){
            return R.fail("明细不能为空");
        }
        // 确认提交
        BigDecimal sumMoney = BigDecimal.ZERO;
        BigDecimal money = BigDecimal.ZERO;
        BigDecimal discount = BigDecimal.ZERO;
//        // 所有收款明细按照订单编号分组
//        Map<Long, List<PaymentPurchaseDetail>> orderMap = payDetails.stream().collect(Collectors.groupingBy(PaymentPurchaseDetail::getOrderId));
//        for(Map.Entry<Long, List<PaymentPurchaseDetail>> entry : orderMap.entrySet()){
//            Long orderId = entry.getKey();
//            List<PaymentPurchaseDetail> orderPayList = entry.getValue();
//        }
        for (PaymentPurchaseDetail detailPO : payDetails) {
            money = money.add(detailPO.getMoney());
            discount = discount.add(detailPO.getDiscount()==null?BigDecimal.ZERO:detailPO.getDiscount());
            sumMoney = sumMoney.add(money).add(discount);
            // 修改代办交货 未对账金额
            AgentDelivery delivery = agentDeliveryService.getById(detailPO.getOrderId());
            if(delivery.getIsPayFinish() == 1){
                throw new Exception(delivery.getDocNo() + "已经收完款了，不能重复收款");
            }
            BigDecimal verifyMonet = delivery.getVerifyMonet();
            verifyMonet = verifyMonet.subtract(detailPO.getMoney());
            detailPO.setOrderTime(delivery.getOrderTime());
            if (payment.getState() == 1){
                payment.setRemitTime(new Date());
                // TODO
                // 新增代办的往来明细
                saveAccountDetails(payment.getCustomerId(), detailPO, 2, 2);
                if (detailPO.getOrderId() == null){
                    throw new Exception("代办交货单不存在");
                }
                delivery.setIsPayFinish(1);
            }else {
                delivery.setIsPayFinish(2);
            }
            delivery.setVerifyMonet(verifyMonet);
            payment.setCustomerId(delivery.getAgentId());
            payment.setCustomerName(delivery.getAgentName());
            agentDeliveryService.updateById(delivery);
        }
        payment.setMoney(NumberUtil.sub(money, payment.getGlobalDiscount()));
        payment.setDiscount(NumberUtil.add(discount, payment.getGlobalDiscount()));

        if (payment.getId() == null){
            payment.setDocNo(CommonConstant.DBFK+ baseMapper.getNextCode());
            payment.setOrderTime(new Date());
            save(payment);
        }else {
            QueryWrapper<PaymentPurchaseDetail> wrapper = new QueryWrapper();
            wrapper.eq("main_id", payment.getId());
            detailService.getBaseMapper().delete(wrapper);

            this.saveOrUpdate(payment);
        }
        // 保存明细
        saveDetail(payment.getId(), payDetails);

        // 状态0结账未付，1实际已付
        if (payment.getState() == 1){
            log.info("更新代办的应收金额：{},{}", payment.getCustomerId(), sumMoney);
            updateArrears(payment.getCustomerId(), sumMoney);

            // 更新总支出
//            FundAccount account_out = accountService.getById(payment.getAccountId());
//            if (account_out != null){
//                BigDecimal totalExpenditure = account_out.getTotalExpenditure();
//                totalExpenditure = totalExpenditure.add(money);
//                account_out.setTotalExpenditure(totalExpenditure);
//                accountService.updateById(account_out);
//            }
//            accountService.addReceipts(payment.getAccountReleases(), Constant.MoneyTYPE.AGENT_OUT, payment.getDocNo(), payment.getId(), payment.getCustomerName());
            accountService.addReceipts(payment.getAccountId(), payment.getMoney(), Constant.MoneyTYPE.AGENT_OUT, payment.getDocNo(), payment.getId(), payment.getCustomerName());

        }
        return R.status(true);
    }

    /**
     * 新增农户，代办的的往来明细
     * @param customerId null
     * @return void
     * @author wrj
     * @since 2024/3/22 上午11:44
     */
    private void saveAccountDetails(Long customerId, PaymentPurchaseDetail detailPO, Integer staffType, Integer detailType){
        // 生成采购，代办的往来明细
        AccountDetails accountDetails = new AccountDetails();
        accountDetails.setStaffType(staffType); // 客商
        accountDetails.setPersonId(customerId);
        accountDetails.setDetailType(detailType); // 付款
        accountDetails.setOrderId(detailPO.getOrderId());
        accountDetails.setOrderTime(detailPO.getOrderTime());
        accountDetails.setDocNo(detailPO.getDocNo());
        accountDetails.setMoney(detailPO.getMoney());
        accountDetails.setDiscount(detailPO.getDiscount());
        log.info("采购，代办收款新增对应的往来明细：{}", JSON.toJSONString(accountDetails));
        accountDetailsService.save(accountDetails);
    }

    /**
     * 更新客商的应收金额
     *
     * @param money null
     * @return void
     * @author wrj
     * @since 2024/3/22 上午11:47
     */
    private void updateArrears(Long customerId, BigDecimal money){
        // 更新待办的应收金额
        AddressBook addressBook = addressBookService.getById(customerId);
        BigDecimal arrears = addressBook.getArrears();
        // 减去该订单代办应收金额
        arrears = arrears.subtract(money);
        addressBook.setArrears(arrears);
        addressBookService.updateById(addressBook);
    }

    /**
     * 删除采购/代办付款
     * @param id null
     * @return R
     * @author wrj
     * @since 2024/3/7 下午4:35
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R deletePayment(Long id) throws Exception {
        PaymentPurchase selectById = baseMapper.selectById(id);
        if (selectById == null){
            throw new Exception("订单不存在");
        }
        // 状态0结账未付，1实际已付
        if (selectById.getState().intValue() != 0){
            throw new Exception("订单不是结账未付状态，不能删除");
        }
        baseMapper.deleteById(id);
        QueryWrapper<PaymentPurchaseDetail> wrapper = new QueryWrapper();
        wrapper.eq("main_id", id);
        // 代办收货
        if (selectById.getOrderType() == 1){
            List<PaymentPurchaseDetail> details = detailService.getBaseMapper().selectList(wrapper);
            for (PaymentPurchaseDetail detail :details) {
                AgentDelivery delivery = agentDeliveryService.getById(detail.getOrderId());
                if (delivery != null){
                    BigDecimal verifyMonet = delivery.getVerifyMonet();
                    verifyMonet = verifyMonet.add(detail.getMoney());
                    delivery.setVerifyMonet(verifyMonet);
                    delivery.setIsPayFinish(0);
                    agentDeliveryService.updateById(delivery);
                }
            }
        }else if (selectById.getOrderType() == 0){
            List<PaymentPurchaseDetail> details = detailService.getBaseMapper().selectList(wrapper);
            for (PaymentPurchaseDetail detail :details) {
                PurchaseDelivery delivery = purchaseDeliveryService.getById(detail.getOrderId());
                if (delivery != null){
                    BigDecimal verifyMonet = delivery.getVerifyMonet();
                    verifyMonet = verifyMonet.add(detail.getMoney());
                    delivery.setVerifyMonet(verifyMonet);
                    delivery.setIsPayFinish(0);
                    purchaseDeliveryService.updateById(delivery);
                }
            }
        }
        detailService.getBaseMapper().delete(wrapper);

//        // 更新总支出
//        FundAccount account_out = accountService.getById(selectById.getAccountId());
//        if (account_out != null){
//            BigDecimal totalExpenditure = account_out.getTotalExpenditure();
//            totalExpenditure = totalExpenditure.subtract(selectById.getMoney());
//            account_out.setTotalExpenditure(totalExpenditure);
//            accountService.updateById(account_out);
//        }

        return R.status(true);
    }

    @Override
    public R agentDeliveryStatistics(AgentDeliveryStatisticsPO po) {
        IPage page = new Page(po.getPage(), po.getLimit());
        IPage<PaymentAgentStatisticsVO> result = this.baseMapper.agentDeliveryStatistics(page, po);
        PaymentAgentStatisticsVO statistics = this.baseMapper.agentDeliveryStatistics2(po);
        List<PaymentAgentStatisticsVO> records = result.getRecords();
        if(CollectionUtil.isNotEmpty(records)){
            List<Long> agentIds = records.stream().map(el -> el.getAgentId()).collect(Collectors.toList());

        }
        Map<String, Object> ads = new HashMap<>();
        ads.put("records", result);
        ads.put("statistics", statistics);
        return R.data(ads);
    }

    @Override
    public R purchaseDeliveryStatistics(PurchaseDeliveryStatisticsPO po) {
        IPage page = new Page(po.getPage(), po.getLimit());
        IPage<PaymentPurchaseStatisticsVO> result = this.baseMapper.purchaseDeliveryStatistics(page, po);
        PaymentPurchaseStatisticsVO statistics = this.baseMapper.purchaseDeliveryStatistics2(po);
        Map<String, Object> ads = new HashMap<>();
        ads.put("records", result);
        ads.put("statistics", statistics);
        return R.data(ads);
    }
}